#include "tab128.h"
#define _CRT_SECURE_NO_WARNINGS


extern t_128 cellsInBandBM[6] = { 
	{0x0000000007FFFFFF,0x0000000000000000}, //0 band 0 rows 123
	{0x003FFFFFF8000000,0x0000000000000000}, //1 band 1 rows 456 
	{0xFFC0000000000000,0x000000000001FFFF}, //2 band 2 rows 789
	{0x81C0E070381C0E07,0x0000000000000703}, //3 stack columns 123
	{0x0E070381C0E07038,0x000000000000381C}, //4 stack columns 456
	{0x70381C0E070381C0,0x000000000001C0E0}, //5 stack columns 789

};

extern t_128 cellsInHouseBM[27] = { 
	{0x00000000000001FF,0x0000000000000000}, //0 row1
	{0x000000000003FE00,0x0000000000000000}, //1
	{0x0000000007FC0000,0x0000000000000000}, //2
	{0x0000000FF8000000,0x0000000000000000}, //3
	{0x00001FF000000000,0x0000000000000000}, //4
	{0x003FE00000000000,0x0000000000000000}, //5
	{0x7FC0000000000000,0x0000000000000000}, //6
	{0x8000000000000000,0x00000000000000FF}, //7
	{0x0000000000000000,0x000000000001FF00}, //8
	{0x8040201008040201,0x0000000000000100}, //9 column 1
	{0x0080402010080402,0x0000000000000201}, //10
	{0x0100804020100804,0x0000000000000402}, //11
	{0x0201008040201008,0x0000000000000804}, //12
	{0x0402010080402010,0x0000000000001008}, //13
	{0x0804020100804020,0x0000000000002010}, //14
	{0x1008040201008040,0x0000000000004020}, //15
	{0x2010080402010080,0x0000000000008040}, //16
	{0x4020100804020100,0x0000000000010080}, //17
	{0x00000000001C0E07,0x0000000000000000}, //18 box 1
	{0x0000000000E07038,0x0000000000000000}, //19
	{0x00000000070381C0,0x0000000000000000}, //20
	{0x0000E07038000000,0x0000000000000000}, //21
	{0x00070381C0000000,0x0000000000000000}, //22
	{0x00381C0E00000000,0x0000000000000000}, //23
	{0x81C0000000000000,0x0000000000000703}, //24
	{0x0E00000000000000,0x000000000000381C}, //25
	{0x7000000000000000,0x000000000001C0E0}, //26
};



//! Table containing the fix data for the 81 cells
CELL_FIX cellsFixedData[81] = {
{ 0, 0, 0, 9, 0,18, 0, "r1c1",{0x80402010081C0FFE,0x0000000000000100}}, //0
{ 1, 0, 1,10, 0,18, 1, "r1c2",{0x00804020101C0FFD,0x0000000000000201}}, //1
{ 2, 0, 2,11, 0,18, 2, "r1c3",{0x01008040201C0FFB,0x0000000000000402}}, //2
{ 3, 0, 3,12, 1,19, 0, "r1c4",{0x0201008040E071F7,0x0000000000000804}}, //3
{ 4, 0, 4,13, 1,19, 1, "r1c5",{0x0402010080E071EF,0x0000000000001008}}, //4
{ 5, 0, 5,14, 1,19, 2, "r1c6",{0x0804020100E071DF,0x0000000000002010}}, //5
{ 6, 0, 6,15, 2,20, 0, "r1c7",{0x10080402070381BF,0x0000000000004020}}, //6
{ 7, 0, 7,16, 2,20, 1, "r1c8",{0x201008040703817F,0x0000000000008040}}, //7
{ 8, 0, 8,17, 2,20, 2, "r1c9",{0x40201008070380FF,0x0000000000010080}}, //8
{ 9, 1, 0, 9, 0,18, 3, "r2c1",{0x80402010081FFC07,0x0000000000000100}}, //9
{10, 1, 1,10, 0,18, 4, "r2c2",{0x00804020101FFA07,0x0000000000000201}}, //10
{11, 1, 2,11, 0,18, 5, "r2c3",{0x01008040201FF607,0x0000000000000402}}, //11
{12, 1, 3,12, 1,19, 3, "r2c4",{0x0201008040E3EE38,0x0000000000000804}}, //12
{13, 1, 4,13, 1,19, 4, "r2c5",{0x0402010080E3DE38,0x0000000000001008}}, //13
{14, 1, 5,14, 1,19, 5, "r2c6",{0x0804020100E3BE38,0x0000000000002010}}, //14
{15, 1, 6,15, 2,20, 3, "r2c7",{0x1008040207037FC0,0x0000000000004020}}, //15
{16, 1, 7,16, 2,20, 4, "r2c8",{0x201008040702FFC0,0x0000000000008040}}, //16
{17, 1, 8,17, 2,20, 5, "r2c9",{0x402010080701FFC0,0x0000000000010080}}, //17
{18, 2, 0, 9, 0,18, 6, "r3c1",{0x804020100FF80E07,0x0000000000000100}}, //18
{19, 2, 1,10, 0,18, 7, "r3c2",{0x0080402017F40E07,0x0000000000000201}}, //19
{20, 2, 2,11, 0,18, 8, "r3c3",{0x0100804027EC0E07,0x0000000000000402}}, //20
{21, 2, 3,12, 1,19, 6, "r3c4",{0x0201008047DC7038,0x0000000000000804}}, //21
{22, 2, 4,13, 1,19, 7, "r3c5",{0x0402010087BC7038,0x0000000000001008}}, //22
{23, 2, 5,14, 1,19, 8, "r3c6",{0x08040201077C7038,0x0000000000002010}}, //23
{24, 2, 6,15, 2,20, 6, "r3c7",{0x1008040206FF81C0,0x0000000000004020}}, //24
{25, 2, 7,16, 2,20, 7, "r3c8",{0x2010080405FF81C0,0x0000000000008040}}, //25
{26, 2, 8,17, 2,20, 8, "r3c9",{0x4020100803FF81C0,0x0000000000010080}}, //26
{27, 3, 0, 9, 3,21, 0, "r4c1",{0x8040E07FF0040201,0x0000000000000100}}, //27
{28, 3, 1,10, 3,21, 1, "r4c2",{0x0080E07FE8080402,0x0000000000000201}}, //28
{29, 3, 2,11, 3,21, 2, "r4c3",{0x0100E07FD8100804,0x0000000000000402}}, //29
{30, 3, 3,12, 4,22, 0, "r4c4",{0x0207038FB8201008,0x0000000000000804}}, //30
{31, 3, 4,13, 4,22, 1, "r4c5",{0x0407038F78402010,0x0000000000001008}}, //31
{32, 3, 5,14, 4,22, 2, "r4c6",{0x0807038EF8804020,0x0000000000002010}}, //32
{33, 3, 6,15, 5,23, 0, "r4c7",{0x10381C0DF9008040,0x0000000000004020}}, //33
{34, 3, 7,16, 5,23, 1, "r4c8",{0x20381C0BFA010080,0x0000000000008040}}, //34
{35, 3, 8,17, 5,23, 2, "r4c9",{0x40381C07FC020100,0x0000000000010080}}, //35
{36, 4, 0, 9, 3,21, 3, "r5c1",{0x8040FFE038040201,0x0000000000000100}}, //36
{37, 4, 1,10, 3,21, 4, "r5c2",{0x0080FFD038080402,0x0000000000000201}}, //37
{38, 4, 2,11, 3,21, 5, "r5c3",{0x0100FFB038100804,0x0000000000000402}}, //38
{39, 4, 3,12, 4,22, 3, "r5c4",{0x02071F71C0201008,0x0000000000000804}}, //39
{40, 4, 4,13, 4,22, 4, "r5c5",{0x04071EF1C0402010,0x0000000000001008}}, //40
{41, 4, 5,14, 4,22, 5, "r5c6",{0x08071DF1C0804020,0x0000000000002010}}, //41
{42, 4, 6,15, 5,23, 3, "r5c7",{0x10381BFE01008040,0x0000000000004020}}, //42
{43, 4, 7,16, 5,23, 4, "r5c8",{0x203817FE02010080,0x0000000000008040}}, //43
{44, 4, 8,17, 5,23, 5, "r5c9",{0x40380FFE04020100,0x0000000000010080}}, //44
{45, 5, 0, 9, 3,21, 6, "r6c1",{0x807FC07038040201,0x0000000000000100}}, //45
{46, 5, 1,10, 3,21, 7, "r6c2",{0x00BFA07038080402,0x0000000000000201}}, //46
{47, 5, 2,11, 3,21, 8, "r6c3",{0x013F607038100804,0x0000000000000402}}, //47
{48, 5, 3,12, 4,22, 6, "r6c4",{0x023EE381C0201008,0x0000000000000804}}, //48
{49, 5, 4,13, 4,22, 7, "r6c5",{0x043DE381C0402010,0x0000000000001008}}, //49
{50, 5, 5,14, 4,22, 8, "r6c6",{0x083BE381C0804020,0x0000000000002010}}, //50
{51, 5, 6,15, 5,23, 6, "r6c7",{0x1037FC0E01008040,0x0000000000004020}}, //51
{52, 5, 7,16, 5,23, 7, "r6c8",{0x202FFC0E02010080,0x0000000000008040}}, //52
{53, 5, 8,17, 5,23, 8, "r6c9",{0x401FFC0E04020100,0x0000000000010080}}, //53
{54, 6, 0, 9, 6,24, 0, "r7c1",{0xFF80201008040201,0x0000000000000703}}, //54
{55, 6, 1,10, 6,24, 1, "r7c2",{0xFF40402010080402,0x0000000000000703}}, //55
{56, 6, 2,11, 6,24, 2, "r7c3",{0xFEC0804020100804,0x0000000000000703}}, //56
{57, 6, 3,12, 7,25, 0, "r7c4",{0x7DC1008040201008,0x000000000000381C}}, //57
{58, 6, 4,13, 7,25, 1, "r7c5",{0x7BC2010080402010,0x000000000000381C}}, //58
{59, 6, 5,14, 7,25, 2, "r7c6",{0x77C4020100804020,0x000000000000381C}}, //59
{60, 6, 6,15, 8,26, 0, "r7c7",{0x6FC8040201008040,0x000000000001C0E0}}, //60
{61, 6, 7,16, 8,26, 1, "r7c8",{0x5FD0080402010080,0x000000000001C0E0}}, //61
{62, 6, 8,17, 8,26, 2, "r7c9",{0x3FE0100804020100,0x000000000001C0E0}}, //62
{63, 7, 0, 9, 6,24, 3, "r8c1",{0x01C0201008040201,0x00000000000007FF}}, //63
{64, 7, 1,10, 6,24, 4, "r8c2",{0x81C0402010080402,0x00000000000007FE}}, //64
{65, 7, 2,11, 6,24, 5, "r8c3",{0x81C0804020100804,0x00000000000007FD}}, //65
{66, 7, 3,12, 7,25, 3, "r8c4",{0x8E01008040201008,0x00000000000038FB}}, //66
{67, 7, 4,13, 7,25, 4, "r8c5",{0x8E02010080402010,0x00000000000038F7}}, //67
{68, 7, 5,14, 7,25, 5, "r8c6",{0x8E04020100804020,0x00000000000038EF}}, //68
{69, 7, 6,15, 8,26, 3, "r8c7",{0xF008040201008040,0x000000000001C0DF}}, //69
{70, 7, 7,16, 8,26, 4, "r8c8",{0xF010080402010080,0x000000000001C0BF}}, //70
{71, 7, 8,17, 8,26, 5, "r8c9",{0xF020100804020100,0x000000000001C07F}}, //71
{72, 8, 0, 9, 6,24, 6, "r9c1",{0x81C0201008040201,0x000000000001FE03}}, //72
{73, 8, 1,10, 6,24, 7, "r9c2",{0x81C0402010080402,0x000000000001FD03}}, //73
{74, 8, 2,11, 6,24, 8, "r9c3",{0x81C0804020100804,0x000000000001FB03}}, //74
{75, 8, 3,12, 7,25, 6, "r9c4",{0x0E01008040201008,0x000000000001F71C}}, //75
{76, 8, 4,13, 7,25, 7, "r9c5",{0x0E02010080402010,0x000000000001EF1C}}, //76
{77, 8, 5,14, 7,25, 8, "r9c6",{0x0E04020100804020,0x000000000001DF1C}}, //77
{78, 8, 6,15, 8,26, 6, "r9c7",{0x7008040201008040,0x000000000001BFE0}}, //78
{79, 8, 7,16, 8,26, 7, "r9c8",{0x7010080402010080,0x0000000000017FE0}}, //79
{80, 8, 8,17, 8,26, 8, "r9c9",{0x7020100804020100,0x000000000000FFE0}}, //80
};



// computed table unit  1_18 &   box 18_27 (3 per unit)
t_128 minilineBM[54] =
{	{0x7,0},{0x38,0},{0x1C0,0}, //0 row1
  	{0xE00,0}, {0x7000,0},{0x38000,0},//1
  	{0x1C0000,0},{0xE00000,0}, {0x7000000,0},//2
  	{0x38000000,0},{0x1C0000000,0},{0xE00000000,0}, //3
  	{0x7000000000,0},{0x38000000000,0},{0x1C0000000000,0}, //4
    {0xE00000000000,0},{0x7000000000000,0},{0x38000000000000,0}, //5
  	{0x1C0000000000000,0},{0xE00000000000000,0},{0x7000000000000000,0}, //6
  	{0x8000000000000000,0x3},{0,0x1c},{0,0xE0}, //7
  	{0,0x700},{0,0x3800},{0,0x1C000},//8
  	{  0x40201,0},  {0x201008000000,0}, {0x8040000000000000,0x100},//9 column 1
    {  0x80402,0},  {0x402010000000,0}, {0x0080000000000000,0x201},//10
 	{ 0x100804,0},  {0x804020000000,0}, {0x0100000000000000,0x402},//11
    { 0x201008,0}, {0x1008040000000,0}, {0x0200000000000000,0x804}, //12
	{ 0x402010,0}, {0x2010080000000,0}, {0x0400000000000000,0x1008}, //13
	{ 0x804020,0}, {0x4020100000000,0}, {0x0800000000000000,0x2010}, //14
	{0x1008040,0}, {0x8040200000000,0}, {0x1000000000000000,0x4020}, //15
	{0x2010080,0},{0x10080400000000,0}, {0x2000000000000000,0x8040}, //16
	{0x4020100,0},{0x20100800000000,0}, {0x4000000000000000,0x10080}, //17 
};
 





PMBF pairinbox;

class GEN_TABLES3{
public:
	GEN_TABLES3(){ 
	//============== 
		Gen4();
	}

	void Gen4();
}gen_tables3;



void GEN_TABLES3::Gen4(){
	pairinbox.SetAll_0();
	// prepare table for pairs in box
	UCAND tpa[]={1+16,1+32,1+128,1+256,
		          2+8,2+32,2+64,2+256,
				  4+8,4+16,4+64,4+128,
				  +128,8+256,16+64,16+256,32+64,32+128
				};
	for(int i=0;i<18;i++)
		pairinbox.SetU(tpa[i]);

}

BF81::BF81(int i1, int i2) {
	ff.clear();
	ff = bitSet[i1];
	ff |= bitSet[i2];	
}

BF81::BF81(char * mode, int i1, int i2) {
	ff.clear();
	if((*mode)=='z'){
		ff = cellsFixedData[i1].z;
		ff &= cellsFixedData[i2].z;
	}
}

BF81::BF81(char * mode, int i1) {
	ff.clear();
	if((*mode)=='z')
		ff = cellsFixedData[i1].z;
}

BF81::BF81(const t_128 &r,const BF81 & r2) {
	this->ff.bitmap128 = r;
	*this &= r2;
}

BF81 BF81::operator | (const BF81 & b) const {
		BF81 w(*this);
		w |= b;
		return w;
	}

BF81 BF81::operator & (const BF81 & b) const {
		BF81 w(*this);
		w.ff &= b.ff;
		return w;
	}

BF81 BF81::operator ^ (const BF81 & b) const {
		BF81 w(*this);
		w.ff ^= b.ff;
		return w;
	}

BF81 BF81::operator -(const BF81 & b) const {
		BF81 w(*this);
		w.ff -= b.ff;
		return w;
	}

int BF81::First() const {
		for(int i = 0; i < 81; i++)
			if(On(i))
				return i;
		return 128;
	}     

USHORT BF81::String(USHORT *r)const  {
	USHORT n=0,dr=0,drb;
	for(int ia=0;ia<4;ia++,dr+=32){
		unsigned int v=ff.bitmap128.m128i_u32[ia];
		if(!v)			continue;
		drb=dr;
		while(1){ // stop as soon as possible
			int mybyte=v&0xff;
			if(mybyte){
				int il=tv_strindex[mybyte];
				for(int  i=tv_strindex[mybyte-1];i<il;i++){
					r[n++]=tv_string[i]+drb;
				}
			}
			v>>=8;
			if(!v)				break;
			drb+=8;
		}
	}
	return n;	
}

void BF81::PackRows(BF16 * rows){
	ff.bitmap128.m128i_u32[3]=0;
	ff.bitmap128.m128i_u32[2]=(rows[7].f>>1) | (rows[8].f<<8);
	ff.bitmap128.m128i_u32[1]=(rows[7].f<<31) | (rows[6].f<<22) | (rows[5].f<<13)
		| (rows[4].f<<4)| (rows[3].f>>5);
	ff.bitmap128.m128i_u32[0]=(rows[3].f<<27) | (rows[2].f<<18) | (rows[1].f<<9)| rows[0].f;
}

void BF81::OrBand(int F,int iband){
	if(!iband) { ff.bitmap128.m128i_u32[0] |= F; return;}
	if(iband==1){
		ff.bitmap128.m128i_u32[0] |= ((F&0x1f)  <<27);
		ff.bitmap128.m128i_u32[1] |=(F>>5);
		return;
	}
	ff.bitmap128.m128i_u32[1] |=( (F & 0x3ff) << 22);
	ff.bitmap128.m128i_u32[2] |=(F>>10);
}


void BF81::LoadZhou(int * F){ //
	SetAll_0(); // must be, don't know why?? 
	ff.bitmap128.m128i_u32[0] =
		(F[0] & BIT_SET_27) | ((F[1] & 0x1f)  <<27);
	ff.bitmap128.m128i_u32[1]|=
		((F[1]& BIT_SET_27)>>5) | ( (F[2] & 0x3ff) << 22);
	ff.bitmap128.m128i_u32[2]=
		( (F[2] & BIT_SET_27)>>10);
}


void BF81::BackZhou(int  * Fx){
	Fx[0]=ff.bitmap128.m128i_u32[0] & BIT_SET_27;
	Fx[1]=((ff.bitmap128.m128i_u32[0]>>27) |
		   (ff.bitmap128.m128i_u32[1]<<5) ) 
	      & BIT_SET_27;
	Fx[2]=((ff.bitmap128.m128i_u32[1]>>22) |
		   (ff.bitmap128.m128i_u32[2]<<10) ) 
	      & BIT_SET_27;

}

USHORT BF81::String(USHORT *r,USHORT digit){
	USHORT n=String(r),x=digit<<7;
	for(int i=0;i<n;i++)
		r[i] |= x; // insert digit to get a UCAND
	return n;
}

USHORT BF81::StringUnit(int unit,USHORT *r) {
	USHORT n=0;
	byte *t = cellsInGroup[unit];
	for(int i=0;i<9;i++,t++)
		if(this->On(*t)) r[n++]=*t;
	return n;
}

USHORT BF81::StringUnit(int unit,USHORT *r,USHORT digit) {
	USHORT n=0;
	byte *t = cellsInGroup[unit];
	for(int i=0;i<9;i++,t++)
		if(this->On(*t)) r[n++]=*t | (digit<<7);
	return n;
}

USHORT BF81::GetRegion(int unit){
	byte *t = cellsInGroup[unit];
	BF16 rr;
	for(int i=0;i<9;i++,t++)
		if(this->On(*t))rr.Set(i);
	return rr.f;
}

BF16 BF81::GetBFRegion(int unit){
	byte *t = cellsInGroup[unit];
	BF16 rr;
	for(int i=0;i<9;i++,t++)
		if(this->On(*t))rr.Set(i);
	return rr;
}

void BF81::Image(BUILDSTRING & zs, int digit,char * lib,int doinit){
	if(doinit)
		zs.Init();
	if(lib)
		zs.Astr(lib);
	USHORT tp[100],ntp=String(tp);
	for(int i=0;i<ntp;i++){
		if(digit>=0 && digit <9)
			zs.Achint(digit);
		zs.Astr(cellsFixedData[tp[i]].pt);
		zs.Aspace();
	}

	zs.Close();
}

void BF81::Store (USHORT * tstore){
	for(int i=0;i<8;i++) tstore[i]=(USHORT) ff.bitmap128.m128i_u16[i]; 
}


void BF81::Re_Load (USHORT * tstore){
	for(int i=0;i<8;i++)  ff.bitmap128.m128i_u16[i]= (unsigned __int16) tstore[i]; 
}

//===================

void PMBF::SetAll_0(){
	bfc[0].SetAll_0();
	for(int i=1;i<9;i++) bfc[i]=bfc[0];
}

int PMBF::operator ==(const PMBF & b) const {
	for(int i=0;i<9;i++) if(!(bfc[i]==b.bfc[i]))
		return false;
	return true;
}

void PMBF::operator &= (const PMBF &b){
	for(int i=0;i<9;i++) bfc[i]&=b.bfc[i];
}

void PMBF::operator |= (const PMBF &b){
	for(int i=0;i<9;i++) bfc[i]|=b.bfc[i];
}

void PMBF::operator &= (const BF81 * bf81){
	for(int i=0;i<9;i++) bfc[i]&=bf81[i];
}

void PMBF::operator -= (const PMBF &b){
	for(int i=0;i<9;i++) bfc[i]-=b.bfc[i];
}


void PMBF::Set(BF16 & digs,int cell){
	for(int i=0;i<9;i++) if(digs.On(i))
		bfc[i]=bfc[0];
}

void PMBF::SetRegion (int dig,int unit,BF16 & pdigs){
	byte * punit=cellsInGroup[unit];
	for(int i=0;i<9;i++) if( pdigs.On(i)){
		Set(dig,punit[i]);
	}
}

void PMBF::Image(BUILDSTRING & zs){
	zs.Init();
	for(int i=0;i<9;i++)
		bfc[i].Image(zs,i,0,0);
}

USHORT PMBF::String(UCAND * t){
	USHORT n=0;
	for(int i=0;i<9;i++)
		n+=bfc[i].String(&t[n],i);
	return n;
}

int PMBF::Count(){
	int n=0;
	for(int i=0;i<9;i++) n+= bfc[i].Count();
	return n;
}

USHORT PMBFONOFF::Stringbits(UCAND * t){
	USHORT n1=bfon.String(t),
		n2=bfoff.String(&t[n1]);
	UCAND * t2=&t[n1];
	for(int i=0;i<n2;i++) t2[i] += 9*128;
	return n1+n2;
}

USHORT PMBFONOFF::String(UCAND * t){
	USHORT n1=bfon.String(t),
		n2=bfoff.String(&t[n1]);
	UCAND * t2=&t[n1];
	for(int i=0;i<n2;i++) t2[i] |= 1<<15;
	return n1+n2;
}


//==================================

USHORT BFSETS::String(USHORT * r) const {
	USHORT n = 0;
	for(int i = 0; i < 3; i++) {
		int m = ff[i].nonzeroOctets(); // 16-bit mask of octets having non-zero bits
		int add8 = 0; //0 for lower 8 bits, 8 for higher 8 bits
		while(m) { //exit if no more octets with bits set
			if((m & 0xFF) == 0) { //lower 8 bits of the mask (== lower 64 bits of the field) are zero, switch to higher bits
				m >>= 8;
				add8 = 8;
			}
			int octetIndexLSB = m & -m; //the rightmost octet having nonzero bit
			int octetIndex = TblBitIndex[octetIndexLSB] + add8 ; //zero based index of this octet within the field
//			int octetIndex = toPos[octetIndexLSB]-1 + add8 ; //zero based index of this octet within the field
			int octetValue = ff[i].bitmap128.m128i_u8[octetIndex];
			do {
				int octetLSB = octetValue & -octetValue; //the rightmost bit set within the value
				int bitIndex = (i * 128) + (octetIndex * 8) + (TblBitIndex[octetLSB]); //convert to zero based index within the fields
//				int bitIndex = (i * 128) + (octetIndex * 8) + (toPos[octetLSB]-1); //convert to zero based index within the fields
				r[n++] = (USHORT)bitIndex; //store
				octetValue ^= octetLSB; //clear the processed bit from the temporay copy
			} while(octetValue); //loop until all bits within this octed are processed
			m ^= octetIndexLSB; //clear the octet processed
		}
	}
	return n;
}

char * BFSETS::XsudoPrint(int mode,char * output){
	//prepare a print of the content in xsudo mode
	//	16 Truths = {2R2457 7R2457 8R2457 9R2457}
    //  17 Links = {2c9 7c68 8c29 9c268 57n1 47n3 2n4 24n5 5n7 8b7}
	char * mymode=(mode)?"nrcb":"NRCB";
	int n=Count();
	if(!n) {output[0]=0; return output;}
	_itoa_s(n,output,10,10); 
	char * p=&output[strlen(output)];
	if (mode)p=stpcpy(p," Links");
	else  p=stpcpy(p," Truths");
	p=stpcpy(p," = {");
	char temp[20];
	for(int ich=0;ich<9;ich++){
		temp[0]=ich+'1';
		for(int itype=0;itype<3;itype++){
			temp[1]=mymode[itype + 1];
			int nd=2;
			for(int j=0;j<9;j++)
				if(On(96+(ich << 5)+9*itype+j))
					temp[nd++]='1'+j;
			if(nd>2){
				temp[nd]=' ';
				temp[nd+1]=0;
				p=stpcpy(p,temp);
			}		
		
		}
	}



	for(int i=0;i<9;i++){
		temp[0]=i+'1';
		temp[1]=mymode[0];
		int nd=2;
		for(int j=0;j<9;j++)
			if(On(9*i+j))
				temp[nd++]='1'+j;
		if(nd>2){
			temp[nd]=' ';
			temp[nd+1]=0;
			p=stpcpy(p,temp);
		}	
	}
	stpcpy(p,"}");
	return output;
}


int BFSETS::Count() const {
	int c = 0;
	for(int i = 0; i < 3; i++)
		c += popcount_128(ff[i].bitmap128.m128i_m128i);
	return c;
}


void ONE_FLOOR:: Go_One_Floorx(PMBF & start){
	fl.onf=this;
	elims=start;
	active_floors.f=0;
	for(int i=0;i<9;i++){
		if(elims.bfc[i].IsEmpty())
			continue;
		f_or.SetAll_0();
		fl.FloorRow(fl.Init(elims.bfc[i]));
		elims.bfc[i]-=f_or;
		if(elims.bfc[i].IsNotEmpty())
			active_floors.Set(i);
	}
}
int ONE_FLOOR::FL::Init(BF81 & fc){
	f_cand = fc;
	  // prepare the list active sets
	sets27.f=0;
	for(int i=0;i<27;i++) 
		if((f_cand & cellsInHouseBM[i]).IsNotEmpty())
			sets27.Set(i);
	int fr=8;
	for(int i=0;i<9;i++) if(sets27.On(i)){
		lastrow=i;
		if(i<fr) fr=i;
	}
	return fr;
}

int ONE_FLOOR::FL::AvanceCand(int icand){
	// cand icand fixed	   find all sets now fixed
	CELL_FIX *pf= &cellsFixedData[icand];
	f_cand-=pf->z;
	sets27.Clear(pf->el);
	sets27.Clear(pf->pl+9);
	sets27.Clear(pf->eb+18);
	int aig=1;
	while(sets27.f && aig){
		aig=0;
		for(int i=0;i<27;i++){
			if(sets27.Off(i)) continue;
			USHORT t[10],n=(f_cand & cellsInHouseBM[i]).String(t);
			if(!n) return 1;
			if(n>1) continue;
			aig=1;
			sets27.Clear(i);
			f_cand-=cellsFixedData[t[0]].z;
		}
	}
	return 0;
}

void ONE_FLOOR::FL::FloorRow(int row){
/* recursive search for row x
   try all possible assignments for the row
*/
  USHORT t[10],n=(f_cand & cellsInHouseBM[row]).String(t);
// changed due to dynamic mode where 1 is possible
//  if(n<2) return; // should never be
  if(n<1) return; // should never be
  for(int i=0;i<n;i++){// all possible entries
	  FL fn((*this));
	  int ii=t[i];
	  if(fn.AvanceCand(ii)) 		  continue;
	  fn.ctllast=1; // to catch solve before last row
	  for(int j=row+1;j<lastrow;j++){// find next active row
		  if(fn.sets27.On(j)){
			  fn.ctllast=0;
			  fn.FloorRow(j);
			  break;
		  }
	  }
	  if((row==lastrow) || fn.ctllast)//   valid perm 
		onf->f_or |= fn.f_cand;
  }

}

int ACTIVERCB::ARCB::Do(int idig,int icell){
	// cand icand fixed   clear icand in other cells
	myor[icell].Set(idig);
	for(int i=icell+1;i<lastcell;i++) 
			if(tcells[i].On(idig)) {
				tcells[i].Clear(idig);
				if(!tcells[i].f) return 1;
			}
	return 0;
}

int ACTIVERCB::ARCB::DoCellForPerm(USHORT cell){
// recursive search for cell x
  for(int ii=0;ii<9;ii++)
    if(tcells[cell].On(ii)){	// all possible entries
		ARCB fn((*this));
		if(fn.Do(ii,cell))   continue; // game locked
		if(cell<lastcell-1){
		  if(fn.DoCellForPerm(cell+1))
			  return 1;
		  continue;
		}
		// no more active cell, this is a valid perm found in last cell
		return 1;
	}
	return 0;
}


int ACTIVERCB::Go_RCBx(PMBF & start,BF16 * dcells,BF81 & actifs,PMBF * do_it){
	int ir=0;
	if(do_it)
		do_it->SetAll_0();
	arcb.or_perms=or_cells;
	active_setsx.f=0;
	for(int i=0;i<27;i++){
		BF81 wel=cellsInHouseBM[i];
		wel &= actifs;
		USHORT tcells[9];
		ncells=wel.String(tcells);
		if(ncells<3)	// should have given a single earlier but this can be in serate mode
			continue;
		arcb.lastcell=ncells;
		for(int j=0;j<ncells;j++){
			or_cells[j].f=0;
			arcb.myor[j].f=0;
			arcb.tcells[j]=dcells[tcells[j]];
		}
		ARCB arcbn(arcb);// to keep free the start
		arcbn.DoCell(0);
		for(int j=0;j<ncells;j++)	if(or_cells[j].f-arcb.tcells[j].f) {
			active_setsx.Set(i);
			break;
		}
		if(do_it){
			ir=1;
			for(int j=0;j<ncells;j++)
				do_it->Set(or_cells[j]-arcb.tcells[j],tcells[j]);
		}
	}	
	return ir;
}

int ACTIVERCB::ARCB::DoCell(USHORT cell){// recursive search for cell x
  int ir=0;
  for(int ii=0;ii<9;ii++)
    if(tcells[cell].On(ii)){	// all possible entries
		ARCB fn((*this));
		if(fn.Do(ii,cell))   continue; // game locked
		if(cell<lastcell-1){
		  if(fn.DoCell(cell+1)){
			  or_perms[cell].Set(ii);	
			  ir=1;
		  }
		  continue;
		}
		// no more active cell, this is a valid perm found in last cell
		or_perms[cell].Set(ii); 
		ir=1;
	}
	return ir;
}

int ACTIVERCB::URDummySet(BF16 * dcells,int n,int for_perm){// Is a UR dummt set active
	arcb.or_perms=or_cells;
	arcb.lastcell=n;
	if(for_perm){ // stop at first perm found
		for(int j=0;j<n;j++){
		arcb.tcells[j]=dcells[j];
		}
		return arcb.DoCellForPerm(0);
	}
	for(int j=0;j<n;j++){
		or_cells[j].f=0;
		arcb.tcells[j]=dcells[j];
	}
	arcb.DoCell(0);
	for(int j=0;j<n;j++)	if(or_cells[j].f-dcells[j].f)  
		return 1;		
	return 0;
}

int CELL_FIX::GetTableRegions(USHORT * tt,CELL_FIX & cell2){
	int n=0;
	if(el==cell2.el) tt[n++]=el;
	if(pl==cell2.pl) tt[n++]=plu;
	if(eb==cell2.eb) tt[n++]=ebu;
	return n;
}

